<template>
    <a-modal v-model:open="visible" title="编辑权限" @cancel="handleCancel" @ok="handleOk">
        <a-form :model="formData" :label-col="{ span: 4 }" :wrapper-col="{ span: 14 }">
            <a-form-item label="权限" name="role">
                <a-tree :tree-data="menuList" showLine :field-names="fieldNames" checkable 
                    v-model:expandedKeys="expandedKeys"
                    v-model:selectedKeys="selectedKeys" 
                    v-model:checkedKeys="checkedKeys"
                    v-model:half-checked-keys="halfCheckedKeys"
                    autoExpandParent 
                    defaultExpandAll />
            </a-form-item>
        </a-form>

        {{ formData }}
    </a-modal>
</template>

<script setup lang="ts">
import { getMenuList } from '@/api/system/permission/auth'
import { setAuth } from '@/api/system/permission/role'
import type { TreeProps } from 'ant-design-vue';
const visible = ref(false)
const records = ref()

interface MenuTreeItem {
    id: number
    name: string
    children: MenuTreeItem[]
}
interface FormData {
    id: string
    role: number[]
}
const formData = reactive<FormData>({
    id: '',
    role: [],
})

const emits = defineEmits(['success'])
// 展开的节点
const expandedKeys = ref<number[]>([])

// 选中的节点
const selectedKeys = ref<number[]>([])

// 选中的节点
const checkedKeys = ref<number[]>([])

// 半选中的节点
const halfCheckedKeys = ref<number[]>([])

// 将字符串转换为数字
const setStringToNumber = (str: any) => {
    if (!str) return []
    // 如果已经是数组，直接返回
    if (Array.isArray(str)) return str.map(item => Number(item))
    // 如果是数字，转换为数组
    if (typeof str === 'number') return [str]
    // 如果是字符串，按逗号分割
    if (typeof str === 'string') {
        const arr = str.split(',')
        return arr.map(item => Number(item))
    }
    return []
}

// 所有节点ID
const getAllNodeIds = (nodes: MenuTreeItem[]): number[] => {
    const ids: number[] = []
    nodes.forEach(node => {
        ids.push(node.id)
        if (node.children?.length) {
            ids.push(...getAllNodeIds(node.children))
        }
    })
    return ids
}

// 过滤函数，只保留 id 和 name 字段
const filterMenuTree = (tree: MenuTreeItem[]): MenuTreeItem[] => {
    return tree.map(item => {
        const filteredItem: MenuTreeItem = {
            id: item.id,
            name: item.name,
            children: []
        };
        if (item.children && item.children.length > 0) {
            filteredItem.children = filterMenuTree(item.children);
        }
        return filteredItem;
    });
}



const fieldNames: TreeProps['fieldNames'] = {
    children: 'children',
    title: 'name',
    key: 'id',
}
const menuList = ref<MenuTreeItem[]>([])

// 初始化选中状态
const initCheckedStatus = (roleIds: number[]) => {
    if (!roleIds?.length) return

    const checked = new Set<number>()
    const halfChecked = new Set<number>()

    // 递归处理节点
    const processNode = (node: MenuTreeItem) => {
        if (!node.children?.length) {
            // 叶子节点
            if (roleIds.includes(node.id)) {
                checked.add(node.id)
            }
            return roleIds.includes(node.id)
        }

        // 处理子节点
        const childrenResults = node.children.map(child => processNode(child))
        const allChildrenChecked = childrenResults.every(r => r)
        const someChildrenChecked = childrenResults.some(r => r)

        // 处理当前节点
        if (allChildrenChecked) {
            checked.add(node.id)
            return true
        } else if (someChildrenChecked || roleIds.includes(node.id)) {
            halfChecked.add(node.id)
            return false
        }
        return false
    }

    // 处理所有根节点
    menuList.value.forEach(node => processNode(node))

    checkedKeys.value = Array.from(checked)
    halfCheckedKeys.value = Array.from(halfChecked)
}

const open = async (record: any) => {
    formData.id = record.id
    formData.role = record.perms ? setStringToNumber(record.perms) : []
    visible.value = true
    const res = await getMenuList()
    menuList.value = filterMenuTree(res.lists)
    // 设置所有节点展开
    expandedKeys.value = getAllNodeIds(menuList.value)
    // 处理初始选中状态
    initCheckedStatus(formData.role)
}

const handleCancel = () => {
    visible.value = false
    expandedKeys.value = []
    selectedKeys.value = []
    checkedKeys.value = []
    halfCheckedKeys.value = []
    formData.role = []
}

const handleOk = async () => {
    try {
        const res = await setAuth(formData)
        emits('success')
        handleCancel()
    } catch (error) {
        console.log(error)
    }
}

// 监听选中状态变化
watch([checkedKeys, halfCheckedKeys], ([newCheckedKeys, newHalfCheckedKeys]) => {
    // 合并完全选中和半选节点，并按数字大小排序
    const allSelectedIds = [...new Set([...newCheckedKeys, ...newHalfCheckedKeys])]
        .sort((a, b) => a - b)
    formData.role = allSelectedIds
}, { deep: true })

defineExpose({
    open
})
</script>
